#ifndef TYPEDEFS_H
#define TYPEDEFS_H


#  include <eq/eq.h>
#  define MESHASSERT  EQASSERT
#  define MESHERROR   EQERROR
#  define MESHWARN    EQWARN
#  define MESHINFO    EQINFO



#include <exception>
#include <iostream>
#include <string>

#ifndef M_PI_2
#  define M_PI_2 1.57079632679489661923
#endif
namespace eqPc{
			enum BodyType
			{
				HEAD,
				FLYSTICK,
			};

			enum ButtonState
			{
				BUTTON_UNPRESSED = 0,
				BUTTON_PRESSED,
				BUTTON_TRIGGERED,
				BUTTON_RELEASED
			};

			enum Button
			{
				BUTTON_TRIGGER,
				BUTTON_1,
				BUTTON_2,
				BUTTON_3,
				BUTTON_4,
			};

			enum TrackingState
			{
				UNINITIALIZED = 0,
				TRACKED,
				UNTRACKED
		
			};
}
namespace pc 
{
    // basic type definitions   
    typedef vmml::vector< 3, GLfloat >    Vertex;
    typedef vmml::vector< 4, GLubyte >    Color;
    typedef vmml::vector< 3, GLfloat >    Normal;
    typedef vmml::matrix< 4, 4, float >   Matrix4f;
    typedef vmml::vector< 4, float >      Vector4f;
    typedef size_t                        Index;
    typedef GLushort                      ShortIndex;    
    
    // mesh exception
    struct MeshException : public std::exception
    {
        explicit MeshException( const std::string& msg ) : _message( msg ) {}
        virtual ~MeshException() throw() {}
        virtual const char* what() const throw() { return _message.c_str(); }
    private:
        std::string _message;
    };
    
    // null output stream that discards everything written to it
    struct NullOStream : std::ostream
    {
        struct NullStreamBuf : std::streambuf
        {
            int overflow( int c ) { return traits_type::not_eof( c ); }
        } _nullBuf;
        
        NullOStream() : std::ios( &_nullBuf ), std::ostream( &_nullBuf ) {}
    };
    
    // wrapper to enable array use where arrays would not be allowed otherwise
    template< class T, size_t d >
    struct ArrayWrapper
    {
        ArrayWrapper() {}
        ArrayWrapper( const T* from ) { memcpy( data, from, sizeof( data )); }
        T& operator[]( const size_t i )
        {
            MESHASSERT( i < d );
            return data[i];
        }
        
        const T& operator[]( const size_t i ) const
        {
            MESHASSERT( i < d );
            return data[i];
        }
        
    private:
        T data[d];
    };
    
    
    // compound type definitions
    typedef vmml::vector< 3, Index >    Triangle;
    typedef ArrayWrapper< Vertex, 2 >   BoundingBox;
    typedef vmml::vector< 4, float >    BoundingSphere;
    typedef ArrayWrapper< float, 2 >    Range;    
    
    // maximum triangle count per leaf node (keep in mind that the number of
    // different vertices per leaf must stay below ShortIndex range; usually
    // #vertices ~ #triangles/2, but max #vertices = #triangles * 3)
    const Index             LEAF_SIZE( 21845 );
    
    // binary mesh file version, increment if changing the file format
    const unsigned short    FILE_VERSION ( 0x0116 );

    // enumeration for the sort axis
    enum Axis
    {
        AXIS_X,
        AXIS_Y,
        AXIS_Z
    };
    inline std::ostream& operator << ( std::ostream& os, const Axis axis )
    {
        os << ( axis == AXIS_X ? "x axis" : axis == AXIS_Y ? "y axis" :
                axis == AXIS_Z ? "z axis" : "ERROR" );
        return os;
    }
    
    // enumeration for the buffer objects
    enum BufferObject
    {
        VERTEX_OBJECT,
        NORMAL_OBJECT,
        COLOR_OBJECT,
        INDEX_OBJECT
    };
    
    // enumeration for the render modes
    enum RenderMode
    {
        RENDER_MODE_IMMEDIATE = 0,
        RENDER_MODE_DISPLAY_LIST,
        RENDER_MODE_BUFFER_OBJECT,
        RENDER_MODE_ALL // must be last
    };
    inline std::ostream& operator << ( std::ostream& os, const RenderMode mode )
    {
        os << ( mode == RENDER_MODE_IMMEDIATE     ? "immediate mode" : 
                mode == RENDER_MODE_DISPLAY_LIST  ? "display list mode" : 
                mode == RENDER_MODE_BUFFER_OBJECT ? "VBO mode" : "ERROR" );
        return os;
    }
    
    // enumeration for kd-tree node types
    enum NodeType
    {
        ROOT_TYPE = 0x07,
        NODE_TYPE = 0xde,
        LEAF_TYPE = 0xef
    };
    
    
    // helper function for MMF (memory mapped file) reading
    inline void memRead( char* destination, char** source, size_t length )
    {
        memcpy( destination, *source, length );
        *source += length;
    }
    
    
    // internally linked null stream, every translation unit gets a copy
    static pc::NullOStream cnul;
}


#endif // MESH_TYPEDEFS_H